#include "obj_map.h"
#include "class.h"
#include "vm.h"
#include "obj_string.h"
#include "obj_range.h"

/**
 * @brief 创建新map对象
*/
ObjMap* new_objMap(VM *vm)
{
    ObjMap *obj_map = ALLOCATE(vm, ObjMap);
    init_objheader(vm, &obj_map->obj_header, OT_MAP, vm->map_class);
    obj_map->capacity = obj_map->count = 0;
    obj_map->entries = NULL;
    return obj_map;
}

/**
 * @brief 计算数字的哈希码
*/
static uint32_t hash_num(double num)
{
    Bits64 bits64;
    bits64.num = num;
    return bits64.bits32[0] ^ bits64.bits32[1];
}

/**
 * @brief 计算对象的哈希码
*/
static uint32_t hash_obj(ObjHeader *obj_header)
{
    switch (obj_header->type)
    {
        case OT_CLASS: // 计算class的哈希值
            return hash_string(((Class *)obj_header)->name->value.start, ((Class *)obj_header)->name->value.length);
        case OT_RANGE:
            ObjRange *obj_range = (ObjRange *)obj_header;
            return hash_num(obj_range->from) ^ hash_num(obj_range->to);
        case OT_STRING: // 对于字符串 直接返回其hash_code
            return ((ObjString *)obj_header)->hash_code;
        default:
            RUNTIME_ERROR("the hashable are objstring, objrange and class.");
    }
    return 0;
}

/**
 * @brief 根据value的类型调用相应的哈希函数
*/
static uint32_t hash_value(Value value)
{
    switch (value.value_type)
    {
        case VT_FALSE:
            return 0;
        case VT_NULL:
            return 1;
        case VT_NUM:
            return hash_num(value.num);
        case VT_TRUE:
            return 2;
        case VT_OBJ:
            return hash_obj(value.obj_header);
        default:
            RUNTIME_ERROR("unsupport type hashed!");
    }
    return 0;
}

/**
 * @brief 在entries中添加entry，如果是新的key则返回true
*/
static bool add_entry(Entry *entries, uint32_t capacity, Value key, Value value)
{
    uint32_t index = hash_value(key) % capacity;
    // 开放定址法
    while (true) 
    {
        if (entries[index].key.value_type == VT_UNDEFINED)
        {
            entries[index].key = key;
            entries[index].value = value;
            return true;
        }
        else if (value_is_equal(entries[index].key, key))
        {
            entries[index].value = value;
            return false;
        }
        index = (index + 1) % capacity;
    }
}

/**
 * @brief 使对象objMap的容量调整到new_capacity
*/
static void resize_map(VM *vm, ObjMap *obj_map, uint32_t new_capacity)
{
    // 先建立一个新的entry数组
    Entry *new_entries = ALLOCATE_ARRAY(vm, Entry, new_capacity);
    uint32_t idx = 0;
    while (idx < new_capacity)
    {
        new_entries[idx].key = VT_TO_VALUE(VT_UNDEFINED);
        new_entries[idx].value =VT_TO_VALUE(VT_FALSE);
        idx ++;
    }
    if (obj_map->capacity > 0)
    {
        Entry *entry_arr = obj_map->entries;
        idx = 0;
        while (idx < obj_map->capacity)
        {
            if (entry_arr[idx].key.value_type != VT_UNDEFINED)
            {
                add_entry(new_entries, new_capacity, entry_arr[idx].key, entry_arr[idx].value);
            }
            idx ++;
        }
    }

    // 把老entry数组空间回收
    DEALLOCATE_ARRAY(vm, obj_map->entries, obj_map->count);
    obj_map->entries = new_entries;
    obj_map->capacity = new_capacity;
}

/**
 * @brief 在objMap中查找key对应的entry
*/
static Entry* find_entry(ObjMap *obj_map, Value key)
{
    if (obj_map->capacity == 0)
    {
        return NULL;
    }
    // 用开放定址法探测
    uint32_t index = hash_value(key) % obj_map->capacity;
    Entry *entry;
    while (true)
    {
        entry = &obj_map->entries[index];
        if (value_is_equal(entry->key, key))
        {
            return entry;
        }
        if (VALUE_IS_UNDEFINED(entry->key) && VALUE_IS_FALSE(entry->value))
        {
            return NULL; // 未找到
        }
        index = (index + 1) % obj_map->capacity;
    }
}

/**
 * @brief 在objMap中实现key和value的关联
*/
void map_set(VM *vm, ObjMap *obj_map, Value key, Value value)
{
    if (obj_map->count + 1 > obj_map->capacity * MAP_LOAD_PERCENT)
    {
        uint32_t new_capacity = obj_map->capacity * CAPACITY_GROW_FACTOR;
        if (new_capacity < MIN_CAPACITY)
        {
            new_capacity = MIN_CAPACITY;
        }
        resize_map(vm, obj_map, new_capacity);
    }
    
    if (add_entry(obj_map->entries, obj_map->capacity, key, value))
    {
        obj_map->count ++;
    }
}

/**
 * @brief 从map查找key对应的value
*/
Value map_get(ObjMap *obj_map, Value key)
{
    Entry *entry = find_entry(obj_map, key);
    if (entry == NULL)
    {
        return VT_TO_VALUE(VT_UNDEFINED);
    }
    return entry->value;
}

/**
 * @brief 回收obj_map.entries占用的空间
*/
void clear_map(VM *vm, ObjMap *obj_map)
{
    DEALLOCATE_ARRAY(vm, obj_map->entries, obj_map->count);
    obj_map->entries = NULL;
    obj_map->capacity = obj_map->count = 0;
}

/**
 * @brief 删除objMap中的key
*/
Value remove_key(VM *vm, ObjMap *obj_map, Value key)
{
    Entry *entry = find_entry(obj_map, key);
    if (entry == NULL)
    {
        return VT_TO_VALUE(VT_NULL);
    }

    // 设置开放定址的伪删除
    Value value = entry->value;
    entry->key = VT_TO_VALUE(VT_UNDEFINED);
    entry->value = VT_TO_VALUE(VT_TRUE);

    obj_map->count --;
    if (obj_map->count == 0)
    {
        clear_map(vm, obj_map);
    }
    else if (obj_map->count < obj_map->capacity / (CAPACITY_GROW_FACTOR) * MAP_LOAD_PERCENT && obj_map->count > MIN_CAPACITY)
    {
        uint32_t new_capacity = obj_map->capacity / CAPACITY_GROW_FACTOR;
        if (new_capacity < MIN_CAPACITY)
        {
            new_capacity = MIN_CAPACITY;
        }
        resize_map(vm, obj_map, new_capacity);
    }
    return value;
}